﻿#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

using Weazel.Math;

using Microsoft.VisualStudio.TestTools.UnitTesting;

#endregion

namespace Weazel.Math.Test
{
  [TestClass]
  public class TestShift
  {
    /**************************************************************************
		 * Left shift (<< operator)
		 **************************************************************************/
    [TestMethod]
    public void TestLeftShift_InvalidShiftValue_1()
    {
      Integer i = new Integer(32, "0x00000001", false);

      try
      {
        Integer r = i << -12;
      }
      catch (ArgumentException)
      {
        return;
      }

      Assert.Fail();
    }

    [TestMethod]
    public void TestLeftShift_Shift0Bits_1()
    {
      Integer i = new Integer(32, "0x00000001", false);

      Integer r = i << 0; // should not change anything

      Assert.AreEqual(i.ToDecimalString(), r.ToDecimalString());
    }

    [TestMethod]
    public void TestLeftShift_ShiftBeyondResultWidth_1()
    {
      Integer i = new Integer(32, "0x00000001", false);
      Integer r = new Integer(32, false);

      Integer.ShiftLeft(ref r, i, new Integer(16, 64, false));

      Assert.IsTrue(r.IsZero());
    }

    [TestMethod]
    public void TestLeftShift_1()
    {
      Integer i = new Integer(32, "0x00000001", false);
      Integer r = i << 1;

      Assert.AreEqual("2", r.ToHexadecimalString());
      Assert.AreEqual(32, r.Width);
    }

    [TestMethod]
    public void TestLeftShift_2()
    {
      Integer i = new Integer(96, "0x000000010000000100000001", false);
      Integer r = i << 1;

      Assert.AreEqual("20000000200000002", r.ToHexadecimalString());
      Assert.AreEqual(96, r.Width);
    }

    [TestMethod]
    public void TestLeftShift_3()
    {
      Integer i = new Integer(96, "0x000000000000000100000000", false);
      Integer r = i << 8;
      
      Assert.AreEqual("10000000000", r.ToHexadecimalString());
      Assert.AreEqual(96, r.Width);
    }


    [TestMethod]
    public void TestLeftShift_4()
    {
      Integer i = new Integer(96, "0x000000000000000000000001", false);
      Integer r = i << 32;
      
      Assert.AreEqual("100000000", r.ToHexadecimalString());
      Assert.AreEqual(96, r.Width);
    }

    [TestMethod]
    public void TestLeftShift_5()
    {
      Integer i = new Integer(96, "0x107237252800120FA0329235", false);
      Integer v = new Integer(8, 36, false);
      Integer r = new Integer(96, false);
      Integer.ShiftLeft(ref r, i, v);      
      Assert.AreEqual("800120fa0329235000000000", r.ToHexadecimalString());
      Assert.AreEqual(96, r.Width);
    }

    [TestMethod]
    public void TestLeftShift_6()
    {
      Integer i = new Integer(96, "0x107237252800120FA0329235", false);
      Integer v = new Integer(8, 36, false);
      Integer r = new Integer(40, false);

      Integer.ShiftLeft(ref r, i, v);

      Assert.AreEqual(40, r.Width);
      Assert.AreEqual("5000000000", r.ToHexadecimalString());      
    }

    // right
    [TestMethod]
    public void TestRightShift_1()
    {
      Integer i = new Integer(32, "0x10000000", false);
      Assert.AreEqual("8000000", (i >> 1).ToHexadecimalString());
    }

    [TestMethod]
    public void TestRightShift_2()
    {
      Integer i = new Integer(96, "0x000000010000000100000001", false);
      Assert.AreEqual("8000000080000000", (i >> 1).ToHexadecimalString());
    }

    [TestMethod]
    public void TestRightShift_3()
    {
      Integer i = new Integer(96, "0x000000000000000100000000", false);
      Assert.AreEqual("1000000", (i >> 8).ToHexadecimalString());
    }


    [TestMethod]
    public void TestRightShift_4()
    {
      Integer i = new Integer(96, "0x000000000000000000000001", false);
      Assert.AreEqual("0", (i >> 32).ToHexadecimalString());
    }

    [TestMethod]
    public void TestRightShift_5()
    {
      Integer i = new Integer(96, "0x123456780000000012345678", false);
      Assert.AreEqual("1234567800000000", (i >> 32).ToHexadecimalString());
    }

    [TestMethod]
    public void TestRightShift_6()
    {
      Integer i = new Integer(96, "0x123456780000000012345678", false);
      Assert.AreEqual("123456780000000", (i >> 36).ToHexadecimalString());
    }

    // test arithmetic right shift

    [TestMethod]
    public void TestArithRightShift_1()
    {
      Integer i = new Integer(96, "8", true);
      Integer j = i << 92 >> 92;
      
      Assert.AreEqual("fffffffffffffffffffffff8", j.ToHexadecimalString());
    }

    [TestMethod]
    public void TestArithRightShift_2()
    {
      Integer i = new Integer(96, "8", true);
      Integer j = i << 88 >> 88;

      Assert.AreEqual("8", j.ToHexadecimalString());
    }
  }
}
